/***********************************************
 **** 版权声明处 **
 ****  为了方便阅读和维护，请严格遵守相关代码规范，谢谢   ****
 *******************************************/
package com.hnisi
{
	/*******************************************
	 **** huangjixin,2012-6-18,上午10:40:41 **
	 **** 请一句话表述该类主要作用  **
	 *******************************************/
	import com.hnisi.events.GraphEvent;
	import com.hnisi.skins.DiagramSkin;
	import com.hnisi.skins.SubGraphSkin;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Keyboard;
	
	import mx.collections.ArrayCollection;
	import mx.core.IVisualElement;
	import mx.core.IVisualElementContainer;
	import mx.core.UIComponent;
	import mx.events.DragEvent;
	import mx.events.FlexEvent;
	import mx.managers.DragManager;
	
	import spark.components.Group;
	
	public class Graph extends Group
	{
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// private 类私有静态变量和静态常量声明处。（全部大写，使用下划线进行分割）
		// 例如：private static const EXAMPLE:String = "example";
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// public 类公有静态变量和静态常量声明处。（全部大写，使用下划线进行分割）
		// 例如：public static const EXAMPLE:String = "example";
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		public static const DATA_FORMAT:String = "hnisi";
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// private 私有变量声明处，请以“_”开头定义变量
		// 例如：private var _example:String;
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		private var currentObject:Object;
		private var _selectedObjects:ArrayCollection;
		
		private var _relatedDis:ArrayCollection;
		
		private var copiedObjects:ArrayCollection;
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// public 公有变量声明处
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		public var diagram:Diagram;
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// 构造函数，初始化相关工作可以放在里面
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		public function Graph()
		{
			super();
			_selectedObjects = new ArrayCollection();
			_relatedDis = new ArrayCollection();
			addDragEventListener();	//添加拖拽事件；
			addEventListener(KeyboardEvent.KEY_DOWN,onKeyboardDown);
			addEventListener(FlexEvent.CREATION_COMPLETE,onCreateComplete);
//			addEventListener(MouseEvent.MOUSE_DOWN,onGraphMouseDown);
		}
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// getter和setter函数
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// 相关事件响应函数和逻辑函数存放处
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		/**
		 * 获得全部对象组； 
		 * @return 
		 * 
		 */
		public function getAllNodes():ArrayCollection{
			var allNodes:ArrayCollection = new ArrayCollection();
			for (var i:int = 0; i < numElements; i++) 
			{
				if(getElementAt(i) is Node){
					allNodes.addItem(getElementAt(i));
				}	
			}
			
			return allNodes;
		}
		
		/**
		 * 获得选择的对象组； 
		 * @return 
		 * 
		 */
		public function getSelectedObjects():ArrayCollection{
			return _selectedObjects;
		}
		
		/**
		 * 清空选择对象组； 
		 * 
		 */
		public function clearSelectedObjects():void
		{
			for each (var object:Object in _selectedObjects) 
			{
				if(object is Node){
					Node(object).isSelected = false;
				}
			}
			
			_selectedObjects.removeAll();
		}//clearSelectedObjects结束
		
		/**
		 * 清空选择对象组； 
		 * 
		 */
		public function deleteSelectedObjects():void
		{
			for each (var object:Object in _selectedObjects) 
			{
				if(object is SubGraph){
					SubGraph(object).graph.deleteAll(SubGraph(object).graph);
					Node(object).dispatchEvent(new GraphEvent(GraphEvent.NODE_REMOVED));
				}else{
					Node(object).dispatchEvent(new GraphEvent(GraphEvent.NODE_REMOVED));
				}
				/*if(object is Node){
					Node(object).dispatchEvent(new GraphEvent(GraphEvent.NODE_REMOVED));
				}*/
				IVisualElementContainer(IVisualElement(object).parent).removeElement(IVisualElement(object));
			}
			_selectedObjects.removeAll();
		}//deleteSelectedObjects结束
		
		/**
		 * 清空选择对象组； 
		 * 
		 */
		public function deleteAll(graph:Graph):void
		{
			for (var i:int = 0; i < graph.numElements; i++) 
			{
				var ele:IVisualElement = graph.getElementAt(i); 
				if(ele is SubGraph){
					SubGraph(ele).graph.deleteAll(SubGraph(ele).graph);
					
					Node(ele).dispatchEvent(new GraphEvent(GraphEvent.NODE_REMOVED));
				}else{
					if(ele is Node){
						Node(ele).dispatchEvent(new GraphEvent(GraphEvent.NODE_REMOVED));
					}
				}
				
				IVisualElementContainer(ele.parent).removeElement(ele);
			}
		}//deleteSelectedObjects结束
		
		/**
		 * 粘贴选择对象； 
		 * 
		 */
		public function posteObjects():void
		{
			if(!copiedObjects){
				return;
			}
			/*for (var i:int = 0; i < getSelectedObjects().length; i++) 
			{
				var node:Node = getSelectedObjects().getItemAt(i) as Node;
				var cloneNode:Node = node.clone();
				IVisualElementContainer(node.parent).addElement(cloneNode);
				cloneNode.x += cloneNode.width;
				cloneNode.y += cloneNode.height;
				setselected(cloneNode, true);
			}
			
			for each (var node1:Node in copiedObjects) 
			{
				var index:int = getSelectedObjects().getItemIndex(node1);
				getSelectedObjects().removeItemAt(index);
			}*/
			var arr:ArrayCollection  = new ArrayCollection();
			for each (var node:Node in copiedObjects) 
			{
				var cloneNode:Node = node.clone();
				IVisualElementContainer(node.parent).addElement(cloneNode);
				cloneNode.x += cloneNode.width;
				cloneNode.y += cloneNode.height;
//				if(node.parent is Graph){
//					Graph(node.parent).setselected(cloneNode, true);				
//				}
				arr.addItem(cloneNode);
			}
			
			clearSelectedObjects();
			
			for each (node in arr) 
			{
				setselected(node,true);
			}
			
		}//posteObjects结束
		
		/**
		 * 清空选择对象组； 
		 * 
		 */
		public function setselected(node:Node,selected:Boolean):void
		{
			if(selected){
				node.isSelected = true;
				_selectedObjects.addItem(node);
			}else{
				node.isSelected = false;
				var index:int = _selectedObjects.getItemIndex(node);
				if(index > -1){
					_selectedObjects.removeItemAt(index);
				}
			}
			
		}//deleteSelectedObjects结束
		
		
		protected function onCreateComplete(event:FlexEvent):void{
			this.systemManager.getSandboxRoot().removeEventListener(DragEvent.DRAG_START,dragStartHandler);
		}
		/**
		 * 键盘按下； 
		 * @param event
		 * 
		 */
		protected function onKeyboardDown(event:KeyboardEvent):void
		{
			switch (event.keyCode)
			{
				case Keyboard.DELETE: //删除；
					deleteSelectedObjects();
					break;
				case Keyboard.UP:
						moveSelectedObjects(getSelectedObjects(), Keyboard.UP);
					break;
				case Keyboard.DOWN:
					moveSelectedObjects(getSelectedObjects(), Keyboard.DOWN);
					break;
				case Keyboard.LEFT:
					moveSelectedObjects(getSelectedObjects(), Keyboard.LEFT);
					break;
				case Keyboard.RIGHT:
					moveSelectedObjects(getSelectedObjects(), Keyboard.RIGHT);
					break;
				case Keyboard.C: //C键
					copiedObjects = getSelectedObjects();
					break;
				case Keyboard.V: //V键
					posteObjects();
					break;
				default:
					break;
			}
		}
		
		/**
		 * 全选 
		 * 
		 */
		public function selectAll():void
		{
			clearSelectedObjects();
			for (var i:int = 0; i < numElements; i++) 
			{
				var ele:IVisualElement = this.getElementAt(i); 
				if(ele is Node){
					setselected(Node(ele),true);
				}
			}
			
		}
		
		/**
		 * 移动；
		 * @param arrCol
		 * @param direction
		 */
		protected function moveSelectedObjects(arrCol:ArrayCollection, direction:uint):void
		{
			var i:int;
			if (direction == Keyboard.UP)
				for (i=0; i < arrCol.length; i++){
					UIComponent(arrCol[i]).y-=1;
					UIComponent(arrCol[i]).dispatchEvent(new Event("positionChange"));
				}
			else if (direction == Keyboard.DOWN)
				for (i=0; i < arrCol.length; i++){
					UIComponent(arrCol[i]).dispatchEvent(new Event("positionChange"));
					UIComponent(arrCol[i]).y+=1;
				}
			else if (direction == Keyboard.LEFT)
				for (i=0; i < arrCol.length; i++){
					UIComponent(arrCol[i]).dispatchEvent(new Event("positionChange"));
					UIComponent(arrCol[i]).x-=1;
				}
			else if (direction == Keyboard.RIGHT)
				for (i=0; i < arrCol.length; i++){
					UIComponent(arrCol[i]).dispatchEvent(new Event("positionChange"));
					UIComponent(arrCol[i]).x+=1;
				}
			
		}
		
		/**
		 * 拖拽侦听；
		 */
		public function removeDragEventListener():void
		{
			this.removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
			this.removeEventListener(DragEvent.DRAG_DROP, dragDropHandler);
		}
		
		/**
		 * 拖拽侦听；
		 */
		public function addDragEventListener():void
		{
			this.addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
			this.addEventListener(DragEvent.DRAG_DROP, dragDropHandler);
		}
		
		/**
		 * 拖放函数； 
		 * @param event
		 * 
		 */
		protected function dragStartHandler(event:DragEvent):void
		{
		
		}
		/**
		 * 拖放函数； 
		 * @param event
		 * 
		 */
		protected function dragDropHandler(event:DragEvent):void
		{
			var object:Object=event.dragSource.dataForFormat(Graph.DATA_FORMAT);
			var classType:String=object.ClassType;
			var hDistance:Number=object.hDistance;
			var vDistance:Number=object.vDistance;
			
			var dragInitiator:Node=event.dragInitiator as Node;
			var instance:UIComponent=dragInitiator.clone() as UIComponent;
			instance.x=mouseX - hDistance;
			instance.y=mouseY - vDistance;
			
			addElement(instance);
//			AdonerPlayer.play(instance as Node);
			invalidateProperties();
			clearSelectedObjects();
			setselected(instance as Node,true);
			setFocus();
			
			dispatchEvent(new DragEvent(DragEvent.DRAG_COMPLETE));
		}
		
		protected function dragEnterHandler(event:DragEvent):void
		{
			if (event.dragSource.hasFormat(Graph.DATA_FORMAT))
			{
				DragManager.acceptDragDrop(UIComponent(event.currentTarget));
			}
		}
		
		
		
		protected function onGraphMouseDown(event:MouseEvent):void
		{
			setFocus();
		}
		
		/**
		 * 鼠标按下拖拽开始； 
		 * 
		 */
		public function onElementMouseDown(event:MouseEvent):void
		{
			var node:Node;
			if(UIComponent(event.currentTarget) is Node){
				node = UIComponent(event.currentTarget) as Node;
			}
			if(node is Link){
				return; //不对连线做任何操作；
			}
			//-- Ctrl键按下多选的时候；
			if(event.ctrlKey){
				node.isSelected = !node.isSelected;
				if(node.isSelected){
					_selectedObjects.addItem(node);
				}else{
					if (_selectedObjects.contains(node)){
						_selectedObjects.removeItemAt(_selectedObjects.getItemIndex(node));
					}
				}
				
//				event.stopImmediatePropagation();
				event.stopPropagation();
				return;
			}else{
				if(!node.isSelected){
					clearSelectedObjects();
					node.isSelected = true;
					_selectedObjects.addItem(node);				
				}
			}
			
			node.startDrag();
			_relatedDis.removeAll();
			
			//--整体移动；
			for each (var ele:Node in _selectedObjects) 
			{
				var obj:Object = {};
				obj.xDis = node.x - ele.x;
				obj.yDis = node.y - ele.y;
				_relatedDis.addItem(obj);
			}
			
			node.addEventListener(MouseEvent.MOUSE_UP,onEleMouseUp);
			node.addEventListener(MouseEvent.MOUSE_MOVE,onEleMouseMove);
//			event.stopImmediatePropagation();
			event.stopPropagation();
			setFocus();
		}
		
		/**
		 * 拖拽移动； 
		 * @param event
		 * 
		 */
		private function onEleMouseMove(event:MouseEvent):void
		{
			var node:Node = UIComponent(event.currentTarget) as Node;
			var ele:Node;
			//-- 整体移动
			for ( var j:int=0;j<_selectedObjects.length;j++) 
			{
				ele = _selectedObjects[j] as Node;
				if(ele!=node){
					var obj:Object = _relatedDis[j];
					ele.x = node.x - obj.xDis;
					ele.y = node.y - obj.yDis;
				}
			}
			
			var object:UIComponent = UIComponent(event.currentTarget).dropTarget as UIComponent; //下面对象；
			if(!object){
				return;
			}
			
			var graph:Graph;
			var hostCom:UIComponent;
			var point:Point;
			if(!(object.document is DiagramSkin)){//针对根Diagram的话不对其；
				
				if(object.document.hasOwnProperty("hostComponent")){
					hostCom = object.document["hostComponent"] as UIComponent;
				}
				
				if(hostCom && hostCom.hasOwnProperty("graph")){
					graph = hostCom["graph"] as Graph;
				}
				
				if(graph){
					graph.playBoarder();
				}
				
				if(!currentObject){
					currentObject = graph;
				}else if(currentObject != graph){
					Graph(currentObject).clearBoarder();
					currentObject = graph;
				}
				
				for each ( ele in _selectedObjects) 
				{
					if(!graph){
						break;
					}
					if(!graph.inGraph(graph,ele)){
						point = new Point(ele.x,ele.y);
						point = node.parent.localToGlobal(point); //關鍵點；
						point = graph.globalToLocal(point);
						graph.addElement(ele);
						ele.x = point.x;
						ele.y = point.y;
					}
				}
				/*if(graph){
					if(!graph.inGraph(graph,node)){
						point = new Point(node.x,node.y);
						point = node.parent.localToGlobal(point); //關鍵點；
						point = graph.globalToLocal(point);
						graph.addElement(node);
						node.x = point.x;
						node.y = point.y;
					}
				}*/
			}else if(currentObject){
				if(currentObject is Graph){
					Graph(currentObject).clearBoarder();
					
					if(object is Graph){
						for each ( ele in _selectedObjects) 
						{
							var flag:Boolean = false;
							for(var i:int=0;i<Graph(object).numElements;i++) 
							{
								if(Graph(object).getElementAt(i) == ele){
									flag = true;
								}
							}
							if(!flag){
								point = new Point(ele.x,ele.y);
								point = ele.parent.localToGlobal(point); //關鍵點；
								point = Graph(object).globalToLocal(point);
								Graph(object).addElement(ele);
								
								ele.x = point.x;
								ele.y = point.y;
							}							
						}
						
						/*if(!Graph(object).inGraph(Graph(object),node)){
							point = new Point(node.x,node.y);
							point = node.parent.localToGlobal(point); //關鍵點；
							point = Graph(object).globalToLocal(point);
							Graph(object).addElement(node);
							
							node.x = point.x;
							node.y = point.y;
						}*/
					}
				}
			}
			
			event.stopImmediatePropagation();
			event.stopPropagation();
			dispatchEvent(new GraphEvent(GraphEvent.NODE_MOVING));
		}
		
		/**
		 * 拖拽结束； 
		 * @param event
		 * 
		 */
		private function onEleMouseUp(event:MouseEvent):void
		{
			UIComponent(event.currentTarget).stopDrag();
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE,onEleMouseMove);
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP,onEleMouseUp);
			event.stopImmediatePropagation();
			event.stopPropagation();
			dispatchEvent(new GraphEvent(GraphEvent.NODE_MOVED));
			//--清除邊框；
			if(currentObject){
				if(currentObject is Graph){
					Graph(currentObject).clearBoarder();
				}
			}
			
			/*var object:Object = UIComponent(event.currentTarget).dropTarget;
			var point:Point;
			if(object is SubGraphSkin){
				if(!SubGraphSkin(object).graph.containsElement(UIComponent(event.currentTarget))){
					SubGraphSkin(object).graph.addElement(UIComponent(event.currentTarget));
					point = new Point(UIComponent(event.currentTarget).x,UIComponent(event.currentTarget).y);
					point = localToGlobal(point); //關鍵點；
					point = SubGraphSkin(object).graph.globalToLocal(point);
					UIComponent(event.currentTarget).x = point.x;
					UIComponent(event.currentTarget).y = point.y;
				}
			}else if(object is Graph){
				var flag:Boolean = false;
				for(var i:int=0;i<Graph(object).numElements;i++) 
				{
					if(Graph(object).getElementAt(i) == UIComponent(event.currentTarget)){
						flag = true;
					}
				}
				
				if(!flag){
					point = new Point(UIComponent(event.currentTarget).x,UIComponent(event.currentTarget).y);
					point = UIComponent(event.currentTarget).parent.localToGlobal(point); //關鍵點；
					point = Graph(object).globalToLocal(point);
					Graph(object).addElement(UIComponent(event.currentTarget));
					
					UIComponent(event.currentTarget).x = point.x;
					UIComponent(event.currentTarget).y = point.y;
				}
			}*/
		}
		
		public function inGraph(graph:Graph,node:Node):Boolean
		{
			var flag:Boolean;
			for(var i:int=0; i< graph.numElements;i++) 
			{
				var element:IVisualElement = graph.getElementAt(i);
				if(node == element){
					flag = true;
					break;
				}
			}
			
			return flag;
			
		}//inGraph结束
		/**
		 * 根据框选的矩形框设置Node； 
		 * @param interactRect
		 * 
		 */
		public function setNodesSelected(interactRect:Rectangle):void
		{
			//碰撞检测;
			var nElem:int=this.numElements;
			var visualElem:UIComponent;
			var elementRect:Rectangle;
			for (var i:int=0; i < nElem; i++)
			{
				visualElem=this.getElementAt(i) as UIComponent;
				
				elementRect=new Rectangle(visualElem.x, visualElem.y, visualElem.width, visualElem.height);
				var isHit:Boolean=interactRect.intersects(elementRect);  //交叉碰撞
				//var isHit:Boolean=drewRect.containsRect(elementRect);   //包含碰撞
				if (isHit)
				{
					if(visualElem is Node){
						if(visualElem is Link){
						
						}else{
							Node(visualElem).isSelected = true;
							_selectedObjects.addItem(Node(visualElem));
						}
					}
				}
			}
		}//setNodesSelected结束
		
		/**
		 * 绘制边框 
		 * 
		 */
		protected function playBoarder():void
		{
			graphics.clear();
			graphics.lineStyle(4,0xff00ff);
			graphics.drawRect(this.x+2,this.y+2,this.width-4,this.height-4);
		}//playBoarder结束
		
		/**
		 * 清除边框； 
		 * 
		 */
		protected function clearBoarder():void
		{
			graphics.clear();
		}//clearBoarder结束
		/**
		 * 克隆函数； 
		 * @return 
		 * 
		 */
		public function clone():Graph{
			var cloneGraph:Graph = new Graph();
			cloneChildren(this,cloneGraph);
			return cloneGraph;
		}
		
		/**
		 *	规定该容器的孩子必须是Node子后代； 
		 * 
		 */
		public function cloneChildren(graph:Graph,cloneGraph:Graph):void
		{
			for (var i:int = 0; i < graph.numElements; i++) 
			{
				var ele:IVisualElement = graph.getElementAt(i);
				if (ele is Node){
					var cloneNode:Node = Node(ele).clone();
					cloneGraph.addElement(cloneNode);
				}else if(ele is Graph){
					var cloneGra:Graph = Graph(ele).clone();
					cloneGraph.addElement(cloneGra);
				}
			}
			
		}//cloneChildren结束
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// override 覆盖函数
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		override public function addElement(element:IVisualElement):IVisualElement{
			super.addElement(element);
			element.addEventListener(MouseEvent.MOUSE_DOWN,onElementMouseDown);
			return element;
		}
		
	}//类结束
}//包结束